package org.NooLab.somclients.components;

import java.util.ArrayList;
import java.util.Observable;
import java.util.Observer;

import org.NooLab.somclients.comm.TcpAdmin;
import org.NooLab.somclients.components.params.SomClientParamPkgIntf;
import org.NooLab.somclients.components.producer.SomClientProducer;
import org.NooLab.somclients.domains.SomClientPublicIntf;
import org.NooLab.somclients.intf.SomClientControlIntf;
import org.NooLab.utilities.files.DFutils;
import org.NooLab.utilities.logging.PrintLog;


/**
 * 
 * 
 * SomClients are provided as a service.
 * A particular SomCLient may be hibernated, or even not existent at any time;
 * 
 * it will be created or reactivated by the framing application = this class = the SomClients;
 * 
 * Both, the creation and the reactivation is based on parameters, of course, which include
 *  - the type of the client (defined in the interface of the SomClient "SomClientIntf")
 *  - the parameters to create or select it, 
 *    which includes any content filter, such as particular words or documents   
 * 
 * 
 * That means, that we have a dedicated data store, which contains the parameters and filters
 * and some visible form (or a de-serializer)
 * ... it might load the list of serialized objects on startup, keeping them in a mem list 
 * 
 * The parameters are introduced via an object that implements the respective interface
 * 
 * 
 * The SomClients framework is started very "soon", just as iTexx itself starts... 
 * There is only 1 instance of it, which keeps a receptor queue running.
 * 
 * The base instance, which is a non-targeted SOM as in the websom, is started as soon as 
 * basic Astor SOM has been initialized, ensuring that there is the astornodes db
 * 
 * In some way, it may be considered as the heart of the whole iTexx framework
 *
 */
public class SomClients {
	
	SomClientsProperties scsProperties ;
	SomClientsFactory somClientsFactory;
	
	/** this is a queue of parameter packages.
	 *  instances of SomClients are created by feeding parameter packages into this queue! */
	WaitingParamPackages waitingPackages ; 

	
	
	
	ArrayList<SomClient> somClients ;
	
	TcpAdmin tcpAdmin;
	
	boolean isRunning=false;
	
	PrintLog out;

	
	// ========================================================================
	public SomClients(SomClientsFactory factory, SomClientsProperties scsProps) throws Exception{
		
		if ((factory==null) || (scsProps==null) ){
			throw(new Exception("No direct instantiation possible for this object."));
		}
		
		scsProperties = scsProps;
		somClientsFactory = factory ;
		
		out = factory.out ;
		
		DFutils.createPath( scsProperties.getHomeDir(), "/"); 
		
		
		waitingPackages = new WaitingParamPackages(this);
		
		
		tcpAdmin = new TcpAdmin(this, scsProps);
		tcpAdmin.createTcpServiceBox() ;
		
		(new SCliAssimilator()).start();
		
		if (isRunning){
			out.print(1, "SomClients' engine is running now, awaiting initialization...");
		}
		
	}
	// ========================================================================
	
	
	public void stop(){
		isRunning=false;
	}
	
	class SCliAssimilator implements Runnable{

		
		Thread sciprocess;
		
		public SCliAssimilator(){
			
			sciprocess = new  Thread(this,"sciprocess");
			
		}
		
		public void start(){
			sciprocess.start();
			
			int z=0;
			while ((isRunning==false) && (z<1000)){
				out.delay(5); z++;
			}
			
		}
		
		@Override
		public void run() {
			 
			SomClientParamPkgIntf pp ;
			
			out.delay(5);
			isRunning = true;
			
			while (isRunning){
				
				if (waitingPackages.size()>0){
					
					pp = waitingPackages.items.get(0);

					new SomClientProducer(pp);
					
					out.delay(200);
					
					waitingPackages.items.remove(0) ;
				}else{
					PrintLog.Delay(500);	
				}
			} // ->
			
			
		} // process
		
	}

	
	class ClientRegistration implements Observer{

		@Override
		public void update(Observable clientObj, Object climsgObj) {
			// 
			
		}
	
		
		
	}
	
	
	
	// ------------------------------------------------------------------------
	public SomClientStateDescription getStateOfSomClient(String byThisGuid) {
		//  
		SomClientStateDescription scd = null;
		SomClient sc = getSomClientInstance(byThisGuid) ;
		 
		scd = sc.getSomClientStateDescription();
		
		return scd;
	}


	public void setControlToSomClient(SomClientControlIntf control) {
		String guid;
		SomClient _sc ;
		
		
		guid = control.getGuid();
		
		_sc  =getSomClientInstance(guid) ;
		
		_sc.importControl(control);
	}


	private SomClient getSomClientInstance(String guid) {

		SomClient _sc, sc =null;
		
		for (int i=0;i<somClients.size();i++){
			_sc = somClients.get(i);
			if (_sc.getGuid().contentEquals(guid) ){
				sc = _sc ;
				break ;
			}
		}

		return sc;
	}


	public SomClientPublicIntf getSomClient(String guid) {
		
		return getSomClientInstance(guid);
	}
	public PrintLog getOut() {
		return out;
	}
}















